#ifndef TCP_HANDLE_BASE_H
#define TCP_HANDLE_BASE_H

#include <stdint.h>
#include <string>
#include "reactor_handler.h"
#include "const.h"

class CReactor;
class CTcpHandleBase;

class ITCPPacketHandleSink
{
public:
    virtual ~ITCPPacketHandleSink() {};

public:
    virtual int OnConnect(
        CTcpHandleBase* pTcpHandleBase,
        const char* pszPeerIP,
        unsigned short ushPeerPort) = 0;

	/*
	 *	Recv a complete PDU
	 */
    virtual int OnRecv(
        CTcpHandleBase* pTcpHandleBase,
        char* pBuffer,
        uint32_t nBufLen,
        uint32_t nLeft) = 0;

	/*
	 *	Recv a break PDU
	 */
    virtual int OnBreakRecv(
        CTcpHandleBase* pTcpHandleBase) = 0;

	virtual int OnSend(
		CTcpHandleBase* pTcpHandleBase) = 0;

    virtual int OnClose(
        CTcpHandleBase* pTcpHandleBase,
        int iCloseCode) = 0;
};

class CTcpHandleBase : public ITCPNetHandler
{
    enum
    {
        S_CLOSE = 0,
        S_CONNECTED,
        S_HALF_CONN,
    };
public:
    CTcpHandleBase(uint32_t dwMaxSendBufLen = MAX_PKG_LEN+PKG_HEAD_LEN, 
						uint32_t dwMaxRecvBufLen = MAX_PKG_LEN+PKG_HEAD_LEN);
    virtual ~CTcpHandleBase();
    
    virtual ITCPNetHandler* Clone() const;
    virtual void Reset();
public:

    int Initialize(
        CReactor* pReactor,
        ITCPPacketHandleSink* pSink)
    {
        m_pReactor = pReactor;
        m_pSink = pSink;
        m_cStatus = S_CLOSE;

        return 0;
    }

    bool IsConnected() const { return (m_cStatus == S_CONNECTED); }

    bool IsClosed() const { return (m_cStatus == S_CLOSE); }

    virtual int OnConnect(
        int iConnHandle,
        unsigned int uiPeerHost,
        unsigned short ushPeerPort,
        int iFlag);

    virtual int OnHalfConnect(
        int iConnHandle,
        unsigned int uiPeerHost,
        unsigned short ushPeerPort,
        int iFlag);

    virtual int OnRecv(
        int iConnHandle,
        char* pRecvBuf,
        uint32_t nBufLen,
        int iFlag);

	virtual int OnSend(
		int iConnHandle
		);

    virtual int OnClose(
        int iConnHandle,
        int iCloseCode,
        int iFlag);

	/*
	 *	Send Data Block (Recommend nBufLen < 65532)
	 *  Return: 0 - Send OK; 
	 *         -1 - Send failed, no bytes sent
	 */
    virtual int SendData(
        const char* pSendBuf = NULL,
        uint32_t nBufLen = 0
        );

    virtual int Close();

public:
    int ConnectTCPServer(
        const char* pszIP,
        uint16_t ushPort,
        ITCPNetHandler*& pOutHandler,
        bool	bAsync = false);

    const std::string& GetPeerHostIP() const
    {
        return m_sPeerHostIP;
    }

	uint16_t GetPeerHostPort() const
    {
        return m_ushPeerHostPort;
    }

    int GetConnHandle() const
    {
        return m_iConnHandle;
    }

	void SetConnHandle(uint32_t dwConnHandle)
	{
        m_iConnHandle = dwConnHandle;
	}

    CReactor* GetReactor()
    {
        return m_pReactor;
    }

	/*
	 *	Set User Defined Handle
	 */
	void SetUserHandle(uint64_t ulUserHandle)
	{
		m_ulUserHandle = ulUserHandle;
	}

	uint64_t GetUserHandle() const
	{
		return m_ulUserHandle;
	}

	void SetConnToken(uint32_t dwToken)
	{
		m_dwConnToken = dwToken;
	}

	uint32_t GetConnToken() const
	{
		return m_dwConnToken;
	}

	void SetActiveTimer(uint32_t dwTimer)
	{
		m_dwActiveTimer = dwTimer;
	}

	uint32_t GetActiveTimer() const
	{
		return m_dwActiveTimer;
	}

protected:
    CReactor* m_pReactor;
    ITCPPacketHandleSink* m_pSink;
    int m_iConnHandle;
    std::string m_sPeerHostIP;
	uint16_t m_ushPeerHostPort;

    char* m_achSendBuf;
    char* m_achRecvBuf;
	int m_dwMaxSendBufLen;
	int m_dwMaxRecvBufLen;
	
	int m_dwSendBufLen;
	int m_dwRecvBufLen;

    int m_nSendPos;   // Position of last avail byte in SendBuf
    int m_nRecvPos;   // Position of last avail byte position in RecvBuf

    bool m_bNeedOnSend;

    int m_l_nPacketLen;
    int m_l_nCurrBufSendSize;
    int m_l_nCurrBufRecvSize;
    int m_l_nPos;

    uint8_t m_cStatus;

	uint64_t m_ulUserHandle;
	uint32_t m_dwConnToken;
	uint32_t m_dwActiveTimer;
};

#endif /* TCP_HANDLE_BASE_H */

